package dk.javacode.proxy;

//@formatter:off
/**
 * Implement this interface to create an interceptor.
 * Annotate using the Interceptor annotation on the methods
 * where this InterceptionHandler should be invoked.
 * 
 * Build a proxy using the InterceptorProxy.build() method to 
 * create a proxy that will use this interface (if it's annotated)
 * 
 * 
 * @author Kavi Mellerup
 *
 * @param <E>
 */
//@formatter:on
public interface InterceptionHandler<E> {
	/**
	 * This method will be invoked before the target method is invoked.
	 * 
	 * @param target The target object (the object the target method is invoked on) 
	 * @param args The arguments the target method is invoked with.
	 * @return A value that will be passed to the 'after' method of this interception handler.
	 */
	public abstract Object before(E target, Object[] args);
	
	/**
	 * This method will be invoked after the target method is invoked.
	 * 
	 * @param target The target object (the object the target method is invoked on) 
	 * @param args The arguments the target method was invoked with.
	 * @param chainedResult The object returned by the 'before' method.
	 */
	public abstract void after(E target, Object[] args, Object chainedResult);
	
	/**
	 * This method MUST return the Class object corresponding to the generics of the implementing class.
	 * I.e. if a class declares "implements InterceptionHandler<String>" then this method would return String.class.
	 * 
	 * This method is a workaround to the difficulties of retrieving generics information about classes at runtime.
	 * 
	 * @return This method MUST return the Class object corresponding to the generics of the implementing class.
	 */
	public abstract Class<E> accepts();
}
